package org.openea.eap.module.obpm.service.form.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.openbpm.base.api.exception.BusinessException;
import org.openbpm.base.api.query.QueryFilter;
import org.openbpm.base.core.util.AppUtil;
import org.openbpm.base.core.util.PropertyUtil;
import org.openbpm.base.core.util.StringUtil;
import org.openbpm.base.manager.impl.BaseManager;
import org.openbpm.bus.api.model.IBusTableRel;
import org.openbpm.bus.api.model.IBusinessColumn;
import org.openbpm.bus.api.model.IBusinessObject;
import org.openbpm.bus.api.service.IBusinessObjectService;
import org.openbpm.bus.api.service.IBusinessTableService;
import org.openbpm.form.api.model.FormType;
import org.openea.eap.module.obpm.dao.form.FormDefDao;
import org.openea.eap.module.obpm.service.form.generator.AbsFormElementGenerator;
import org.openea.eap.module.obpm.model.form.FormDef;
import org.openea.eap.module.obpm.model.form.FormTemplate;
import org.openea.eap.module.obpm.model.form.design.FormGroup;
import org.openea.eap.module.obpm.model.form.design.FormOverallArrangement;
import org.openea.eap.module.obpm.model.form.design.FormTab;
import org.openbpm.sys.api.freemark.IFreemarkerEngine;
import org.openbpm.sys.api.model.ISysTreeNode;
import org.openbpm.sys.api.service.ISysTreeNodeService;
import org.openea.eap.module.obpm.service.form.FormDefManager;
import org.openea.eap.module.obpm.service.form.FormTemplateManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service("formDefManager")
public class FormDefManagerImpl
        extends BaseManager<String, FormDef>
        implements FormDefManager {
    protected Logger LOG = LoggerFactory.getLogger(getClass());

    @Resource
    FormDefDao formDefDao;
    @Autowired
    ISysTreeNodeService sysTreeNodeService;
    @Autowired
    IBusinessObjectService businessObjectService;
    @Autowired
    IBusinessTableService businessTableService;
    @Autowired
    FormTemplateManager formTemplateManager;
    @Autowired
    IFreemarkerEngine freemarkEngine;

    public FormDef getByKey(String key) {
        FormDef form = this.formDefDao.getByKey(key);

        return form;
    }


    public void saveBackupHtml(FormDef formDef) {
        String formDefPath = PropertyUtil.getFormDefBackupPath();
        if (StringUtil.isEmpty(formDefPath)) {
            return;
        }

        ISysTreeNode node = this.sysTreeNodeService.getById(formDef.getGroupId());
        String fileName = formDefPath + File.separator + node.getKey() + File.separator + formDef.getKey() + ".html";
        FileUtil.writeUtf8String(formDef.getHtml(), fileName);
    }


    public String getBackupHtml(FormDef formDef) {
        String formDefPath = PropertyUtil.getFormDefBackupPath();
        if (StringUtil.isNotEmpty(formDefPath)) {
            ISysTreeNode node = this.sysTreeNodeService.getById(formDef.getGroupId());
            String fileName = formDefPath + File.separator + node.getKey() + File.separator + formDef.getKey() + ".html";
            formDef.setHtml(FileUtil.readUtf8String(fileName));
        }

        return formDef.getHtml();
    }


    public String generateFormHtml(String boKey, JSONArray templateConfig, String fromType, boolean isGeneraterSubTable) {
        String boDesign = this.businessObjectService.getBoOverallArrangement(boKey);

        if (StringUtil.isNotEmpty(boDesign)) {

            if (FormType.PC_IVIEW.value().equals(fromType)) {
                return generateIviewOverallArrangementFormHtml(boDesign, boKey, templateConfig, isGeneraterSubTable);
            }
            return generateVueOverallArrangementFormHtml(boDesign, boKey, templateConfig, isGeneraterSubTable);
        }


        IBusinessObject businessObject = this.businessObjectService.getFilledByKey(boKey);

        StringBuilder sb = new StringBuilder();
        for (Object object : templateConfig) {
            JSONObject jsonObject = (JSONObject) object;
            String templateKey = jsonObject.getString("templateKey");
            IBusTableRel relation = businessObject.getRelation().find(jsonObject.getString("tableKey"));
            FormTemplate template = this.formTemplateManager.getByKey(templateKey);
            if (template == null) {
                this.LOG.warn("表单模板{}不存在！", templateKey);
                continue;
            }
            Map<String, Object> map = new HashMap<>();
            map.put("relation", relation);


            for (AbsFormElementGenerator generator : AppUtil.getImplInstanceArray(AbsFormElementGenerator.class)) {
                map.put(generator.getGeneratorName(), generator);
            }

            String html = this.freemarkEngine.parseByString(template.getHtml(), map);

            sb.append(html);
        }
        if (sb.length() > 0 && !isGeneraterSubTable) {
            sb.insert(0, "<div class=\"ivu-form ivu-form-label-right\">");
            sb.append("</div>");
        }

        return sb.toString();
    }


    private String generateIviewOverallArrangementFormHtml(String boDesign, String boKey, JSONArray templateConfig, boolean isGeneraterSubTable) {
        FormOverallArrangement formDesign = (FormOverallArrangement) JSON.toJavaObject((JSON) JSON.parseObject(boDesign), FormOverallArrangement.class);
        IBusinessObject businessObject = this.businessObjectService.getFilledByKey(boKey);


        StringBuffer html = new StringBuffer();
        if (CollectionUtil.isNotEmpty(formDesign.getTabList()) && !isGeneraterSubTable) {
            html.append("<Tabs>");
            formDesign.getTabList().forEach(tab -> {
                html.append(" <tab-pane label=\"")
                        .append(tab.getComment())
                        .append("\">");

                html.append(generateGroupsHtml(tab.getGroupList(), businessObject, templateConfig));

                html.append("</tab-pane> ");
            });


            html.append("</Tabs>");
        } else {
            html.append(generateGroupsHtml(formDesign.getGroupList(), businessObject, templateConfig));
        }

        if (html.length() > 0 && !isGeneraterSubTable) {

            String formType = FormType.PC_IVIEW.value();
            html.insert(0, getHtmlBodyTop(formType));
            html.append(getHtmlBodyBottom(formType));
        }

        return html.toString();
    }


    private String generateVueOverallArrangementFormHtml(String boDesign, String boKey, JSONArray templateConfig, boolean isGeneraterSubTable) {

        // 0 prepare
        FormOverallArrangement formDesign = (FormOverallArrangement) JSON.toJavaObject((JSON) JSON.parseObject(boDesign), FormOverallArrangement.class);
        IBusinessObject businessObject = this.businessObjectService.getFilledByKey(boKey);
        StringBuffer html = new StringBuffer();
        boolean isFirst = true;

        // 1 tab  需要优化显示
        if (!isGeneraterSubTable && CollectionUtil.isNotEmpty(formDesign.getTabList())) {

            List<FormTab> tabList = formDesign.getTabList();
            int otherTabs = 0;
            // 1.1 main tab
            for (FormTab tab : formDesign.getTabList()) {
                if (tab.isMainPage()) {
                    if (CollectionUtil.isNotEmpty(tab.getGroupList())) {
                        isFirst = false;
                        html.append(generateGroupsHtml(tab.getGroupList(), businessObject, templateConfig));
                    }
                } else {
                    if (CollectionUtil.isNotEmpty(tab.getGroupList())) {
                        otherTabs++;
                    }
                }
            }
            // 1.2 other tabs
            if (otherTabs > 0) {
                // 1.2.a tab nav
                html.append("<ul class=\"nav nav-tabs\">");
                int index = 1;
                for (FormTab tab : formDesign.getTabList()) {
                    if (tab.isMainPage() || CollectionUtil.isEmpty(tab.getGroupList())) {
                        continue;
                    }
                    String tabComment = tab.getComment();
                    if(StringUtil.isEmpty(tabComment)){
                        tabComment = "tab"+index;
                        tab.setComment(tabComment);
                    }
                    html.append(
                            String.format("<li %s ><a href=\"#%s\"  data-toggle=\"tab\" >%s</a></li>", new Object[]{
                                    isFirst ? "class=\"active\"" : "", tabComment, tabComment
                            }));
                    isFirst = false;
                    index++;
                }
                html.append("</ul> ");

                // 1.2.b tab content
                html.append("<div class=\"tab-content\">");
                for (FormTab tab : formDesign.getTabList()) {
                    if (tab.isMainPage() || CollectionUtil.isEmpty(tab.getGroupList())) {
                        continue;
                    }
                    html.append("<div class=\"tab-pane ").append(isFirst ? "active" : "").append("\" id=\"").append(tab.getComment()).append("\">")
                            .append(generateGroupsHtml(tab.getGroupList(), businessObject, templateConfig))
                            .append("</div>");
                    isFirst = false;
                }
                html.append("</div>");
            }
        }

        // 2 subTable or no tab
        if (isGeneraterSubTable || isFirst) {
            html.append(generateGroupsHtml(formDesign.getGroupList(), businessObject, templateConfig));
        }

        // 3. check
        if (html.length() > 0 && !isGeneraterSubTable) {
            String formType = FormType.PC_VUE.value();
            html.insert(0, getHtmlBodyTop(formType));
            html.append(getHtmlBodyBottom(formType));
        }

        return html.toString();
    }

    private String getHtmlBodyTop(String fromType) {
        if (FormType.PC_IVIEW.value().equals(fromType)) {
            return HtmlBodyTopIview;
        }
        return HtmlBodyTopVue;
    }

    private String getHtmlBodyBottom(String fromType) {
        return "</div>";
    }

    private final String HtmlBodyTopIview = "<div class=\"ivu-form ivu-form-label-right\">" +
            "<script>\n" +
            "    window.custFormComponentMixin ={\n" +
            "        data: function () {\n            return {\"test\":\"helloWorld\"};\n        },\n" +
            "        created:function(){\n            console.log(\"脚本将会混入自定义表单组件中...\");\n        }," +
            "        methods:{\n" +
            "            testaaa:function(){alert(1)}\n        }\n" +
            "    }\n" +
            "</script>";
    private final String HtmlBodyTopVue = "<div class=\"ivu-form ivu-form-label-right\">" +
            "<script>\n" +
            "    window.custFormComponentMixin ={\n" +
            "        data: function () {\n            return {\"test\":\"helloWorld\"};\n        },\n" +
            "        created:function(){\n            console.log(\"脚本将会混入自定义表单组件中...\");\n        }," +
            "        methods:{\n" +
            "           testaaa:function(){alert(1)},\n" +
            "           custValid:function(){  \n\t\t\t\t// 执行业务校验，return false则终止提交 \n\t\t\t\treturn true;  \n           }\n        }\n" +
            "    }\n" +
            "</script>";


    private String generateGroupsHtml(List<FormGroup> groupList, IBusinessObject businessObject, JSONArray templateConfig) {
        if (groupList == null) {
            return "";
        }
        StringBuilder groupHtml = new StringBuilder();
        groupList.forEach(group -> {
            String tableKey = group.getKey();
            String templateKey = getTemplateKey(templateConfig, tableKey);

            if (StringUtil.isEmpty(templateKey)) {
                return;
            }
            IBusTableRel relation = businessObject.getRelation().find(tableKey);
            FormTemplate template = this.formTemplateManager.getByKey(templateKey);


            Map<String, Object> map = new HashMap<>();
            map.put("relation", relation);
            group.setTableRelation(relation);

            map.put("group", group);


            for (AbsFormElementGenerator generator : AppUtil.getImplInstanceArray(AbsFormElementGenerator.class)) {
                map.put(generator.getGeneratorName(), generator);
            }
            this.LOG.debug("templateKey:{},tableKey:{}", templateKey, tableKey);
            String html = this.freemarkEngine.parseByString(template.getHtml(), map);

            groupHtml.append(html);
        });

        return groupHtml.toString();
    }


    private String getTemplateKey(JSONArray templateConfig, String tableKey) {
        for (Object object : templateConfig) {
            JSONObject jsonObject = (JSONObject) object;
            if (jsonObject.getString("tableKey").equals(tableKey)) {
                return jsonObject.getString("templateKey");
            }
        }

        throw new BusinessException("tableKey :" + tableKey + "尚未选择模板，请选择模板后生成表单");
    }


    public List<Map> queryWithBo(QueryFilter queryFilter) {
        return this.formDefDao.queryWithBo(queryFilter);
    }


    public String genColumnHtml(String boKey, String formType, String tableKey, String columnKey) {
        IBusinessObject businessObject = this.businessObjectService.getFilledByKey(boKey);
        IBusTableRel relation = businessObject.getRelation().find(tableKey);
        IBusinessColumn column = relation.getTable().getColumnByKey(columnKey);

        FormType type = FormType.fromValue(formType);

        AbsFormElementGenerator formGenerator = (AbsFormElementGenerator) AppUtil.getBean(type.getBeanId());
        if (formGenerator == null) return null;

        return formGenerator.getColumn(column, relation);
    }
}
